
// <copyright file="IOHelper.cs" company="Subhadra Software Solutions">
//   
// </copyright>
// <summary>
//   The io helper.
// </summary>

namespace SubhadraSolutions.Sharp.Utils.IO
{
    using System;
    using System.Diagnostics;
    using System.IO;

    using SubhadraSolutions.Sharp.Utils.Diagnostics;

    /// <summary>
    /// The io helper.
    /// </summary>
    public static class IOHelper
    {
        #region Public Methods and Operators

        /// <summary>
        /// The delete file.
        /// </summary>
        /// <param name="fileName">
        /// The file name.
        /// </param>
        /// <param name="checkExists">
        /// The check exists.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool DeleteFile(string fileName, bool checkExists)
        {
            if (checkExists)
            {
                if (File.Exists(fileName))
                {
                    return deleteFileUnsafe(fileName);
                }

                return true;
            }

            return deleteFileUnsafe(fileName);
        }

        /// <summary>
        /// The is file locked.
        /// </summary>
        /// <param name="fileName">
        /// The file name.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool IsFileLocked(string fileName)
        {
            FileStream stream = null;
            try
            {
                stream = File.Open(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
            }
            catch (IOException)
            {
                // the file is unavailable because it is:
                // still being written to
                // or being processed by another thread
                // or does not exist (has already been processed)
                return true;
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }
            }

            // file is not locked
            return false;
        }

        /// <summary>
        /// The move file.
        /// </summary>
        /// <param name="source">
        /// The source.
        /// </param>
        /// <param name="dest">
        /// The dest.
        /// </param>
        /// <param name="checkExists">
        /// The check exists.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool MoveFile(string source, string dest, bool checkExists)
        {
            if (checkExists)
            {
                if (File.Exists(source))
                {
                    return moveFileUnsafe(source, dest);
                }

                return true;
            }

            return moveFileUnsafe(source, dest);
        }

        /// <summary>
        /// The resolve path.
        /// </summary>
        /// <param name="path">
        /// The path.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string ResolvePath(string path)
        {
            return ResolvePath(path, ProcessHelper.RootPathOfApplication);
        }

        /// <summary>
        /// The resolve path.
        /// </summary>
        /// <param name="path">
        /// The path.
        /// </param>
        /// <param name="basePath">
        /// The base path.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string ResolvePath(string path, string basePath)
        {
            return Path.IsPathRooted(path) ? path : Path.Combine(basePath, path);
        }

        #endregion Public Methods and Operators

        #region Methods

        /// <summary>
        /// The delete file unsafe.
        /// </summary>
        /// <param name="fileName">
        /// The file name.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        private static bool deleteFileUnsafe(string fileName)
        {
            try
            {
                File.Delete(fileName);
                return true;
            }
            catch (FileNotFoundException)
            {
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                return false;
            }
        }

        /// <summary>
        /// The move file unsafe.
        /// </summary>
        /// <param name="source">
        /// The source.
        /// </param>
        /// <param name="dest">
        /// The dest.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        private static bool moveFileUnsafe(string source, string dest)
        {
            int attemptCount = 0;
            while (true)
            {
                try
                {
                    File.Move(source, dest);
                    return true;
                }
                catch (FileNotFoundException)
                {
                    return true;
                }
                catch (IOException ex)
                {
                    Debug.WriteLine(ex);
                    if (attemptCount > 1)
                    {
                        return false;
                    }

                    attemptCount++;
                    if (!DeleteFile(dest, false))
                    {
                        return false;
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex);
                    return false;
                }
            }
        }

        #endregion Methods
    }
}